package hgin

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"log/slog"
	"strings"
	"time"
)

const CtxSetResBody = "ctx_set_res_body"        //Key 响应报文，用于记录日志
const CtxDisableResLog = "CtxDisableResBodyLog" //Key 标记不记录响应报文日志,一般用于响应报文较大的接口

// MiddlewareLogger 中间件：日志记录
func MiddlewareLogger(ctx *gin.Context) {
	var (
		err    error
		beg    = time.Now()
		req    string
		res    string
		errMsg = ""
		logJ   = strings.Contains(ctx.GetHeader("Content-Type"), "application/json")
	)
	//非JSON格式接口不记录日志
	if !logJ {
		ctx.Next()
		return
	}

	defer func() {
		if e := recover(); e != nil {
			err = e.(error)
		}
		if err != nil {
			errMsg = "|异常信息：" + err.Error()
		}
		slog.Info(fmt.Sprintf("接口地址：%s  |请求报文：%s  |响应报文：%s %s |耗时：%vms  |IP：%s  ", ctx.Request.RequestURI, req, res, errMsg, time.Since(beg).Milliseconds()), RemoteIP(ctx))
	}()

	var bBytes []byte
	bBytes, err = io.ReadAll(ctx.Request.Body)
	if err != nil {
		ctx.Abort()
		return
	}
	req = string(bBytes)
	ctx.Request.Body = io.NopCloser(bytes.NewBuffer(bBytes))

	ctx.Next()

	// 响应报文，如果标记禁用响应日志则不记录。例如图片验证码，返回报文是图片无法阅读，所以无需记录
	if _, exists := ctx.Get(CtxDisableResLog); !exists {
		res = ctx.GetString(CtxSetResBody)
	} else {
		res = " -- disable res log -- "
	}
}
